package com.irdstudio.efp.esb.service.impl.zx;

import static com.irdstudio.basic.sequence.service.DefaultPatternDescriptor.DAY;
import static com.irdstudio.basic.sequence.service.DefaultPatternDescriptor.HOUR;
import static com.irdstudio.basic.sequence.service.DefaultPatternDescriptor.MIN;
import static com.irdstudio.basic.sequence.service.DefaultPatternDescriptor.MONTH;
import static com.irdstudio.basic.sequence.service.DefaultPatternDescriptor.SECOND;
import static com.irdstudio.basic.sequence.service.DefaultPatternDescriptor.SEQ;
import static com.irdstudio.basic.sequence.service.DefaultPatternDescriptor.YEAR_2;
import static java.util.Collections.singletonList;

import java.util.Objects;
import java.util.Optional;
import java.util.function.Function;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.irdstudio.basic.framework.core.exception.ESBException;
import com.irdstudio.basic.framework.core.util.SpringContextUtils;
import com.irdstudio.basic.sequence.service.DefaultPatternDescriptor;
import com.irdstudio.basic.sequence.service.PatternDescriptor;
import com.irdstudio.basic.sequence.service.facade.PatternedLimitableSeqService;
import com.irdstudio.efp.esb.common.client.resp.EsbRespServiceBean;
import com.irdstudio.efp.esb.common.client.resp.EsbRespSysHeadBean;
import com.irdstudio.efp.esb.service.bo.req.BaseZXReqBean;
import com.irdstudio.efp.esb.service.bo.req.ZX10001QueryReports;
import com.irdstudio.efp.esb.service.bo.req.ZXQueryReports;
import com.irdstudio.efp.esb.service.bo.resp.zx.BaseZXResBean;
import com.irdstudio.efp.esb.service.bo.resp.zx.ZXResponseReport;
import com.irdstudio.efp.esb.service.client.ESBClientFactory;
import com.irdstudio.efp.esb.service.client.impl.MSESBBeanCreator;
import com.irdstudio.efp.esb.service.facade.zx.ZXService;
import com.irdstudio.efp.esb.service.vo.zx.ZXVO;

/**
 * @description:征信黑名单接口基类
 * @param <Q> 请求查询的报文类型
 * @param <P> 接口返回的结果类型
 * @date:2018年12月15日 上午10:29:31
 * @author:hengyh
 */
public abstract class BaseZXService<Q extends ZXQueryReports, P extends ZXResponseReport> implements ZXService<Q> {
	
	private static Logger log = LoggerFactory.getLogger(BaseZXService.class);
	
	public static final String ZX_SUCCESS_STATUS = "1";
	
	private static final PatternDescriptor pattern = 
			DefaultPatternDescriptor.of("ZX" + YEAR_2 + MONTH + DAY + HOUR + MIN + SECOND + SEQ, 10);
	
	public ZXVO service(Q queryReports) throws Exception {
		log.info("处理卡中心接口开始， 请求参数：" + queryReports);
		ZXConfig local = BaseZXService.config;
		BaseZXReqBean<Q> reqBean = new BaseZXReqBean.Builder<Q>()
				.withSysId(local.getSystemId())
				.withUsrID(local.getUserId())
				.withPKey(local.getpKey())		
				.withRqsID(queryIdGenerate()) /* 生成唯一的queryId */
				.withQryRptsInfArry(singletonList(queryReports))
				.build();
		
		preProcess(reqBean);
		
		//挡板
		/*if (queryReports instanceof ZX10001QueryReports) {
			BaseZXResBean<P> resBean = null;
			return postProcess(reqBean, resBean);
		}else {
			EsbRespServiceBean esbRespServiceBean = ESBClientFactory.buildClient()
					.withBody(reqBean)
					.withTradeNo(tradeNo())
					.withScene(scene())
					.create()
					.sendAndReceive();
			EsbRespSysHeadBean esbRespSysHeadBean = esbRespServiceBean.getSysHead();
			BaseZXResBean<P> resBean = esbRespServiceBean.getBody(converter());
			if (Objects.equals(esbRespSysHeadBean.getRetSt(), "0")) {
				StringBuilder errMsg = new StringBuilder("调用卡中心接口异常");
				Optional.ofNullable(resBean).map(BaseZXResBean::getWrongInf)
				.ifPresent(s -> errMsg.append(",错误信息: ").append(s));
				throw new ESBException(errMsg.toString());
			}
			return postProcess(reqBean, resBean);
		}*/
		try {
			EsbRespServiceBean esbRespServiceBean = ESBClientFactory.buildClient()
					.withBody(reqBean)
					.withTradeNo(tradeNo())
					.withScene(scene())
					.withESBBeanFactory((MSESBBeanCreator) SpringContextUtils.getBean("MSESBBeanCreator"))
					.create()
					.sendAndReceive();
			EsbRespSysHeadBean esbRespSysHeadBean = esbRespServiceBean.getSysHead();
			BaseZXResBean<P> resBean = esbRespServiceBean.getBody(converter());
			if (Objects.equals(esbRespSysHeadBean.getRetSt(), "0")) {
				StringBuilder errMsg = new StringBuilder("调用卡中心接口异常");
				Optional.ofNullable(resBean).map(BaseZXResBean::getWrongInf)
				.ifPresent(s -> errMsg.append(",错误信息: ").append(s));
				throw new ESBException(errMsg.toString());
			}
			return postProcess(reqBean, resBean);
		} catch (ESBException e) {
			log.error(e.getMessage());
			throw e;	
		} catch (Exception e) {
			log.error(e.getMessage());
			throw new ESBException(e);
		}
		
		
	}
	
	/* 对queryReports进行预处理（可选),由子类实现  */
	protected void preProcess(BaseZXReqBean<Q> reqBean) { };
	/* 对接口返回结果进行处理，并返回包装后的结果 */
	protected abstract ZXVO postProcess(BaseZXReqBean<Q> reqBean, BaseZXResBean<P> resBean) throws Exception;
	/* 各接口的交易码 */
	protected abstract String tradeNo();
	/* 各接口的服务场景 */
	protected abstract String scene();
	/* 各接口实现需提供将 返回JSON 转换为 Bean 的转换策略 */
	protected abstract Function<String , BaseZXResBean<P>> converter() ;
	
	private String queryIdGenerate() throws Exception {
		PatternedLimitableSeqService sequenceService = (PatternedLimitableSeqService) SpringContextUtils.getBean("defaultSeqService");
		return sequenceService.getPatternedSequence("ZX", pattern);
	}
	
	protected static ZXConfig config ;
	static void setConfig(ZXConfig config) {
		BaseZXService.config = config;
	}
}
